package com.ayjsolutions.marcadoresfutbol.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import com.ayjsolutions.marcadoresfutbol.ListaPartidosAdapter;
import com.ayjsolutions.marcadoresfutbol.MainActivity;
import com.ayjsolutions.marcadoresfutbol.PartidoLista;
import com.ayjsolutions.marcadoresfutbol.database.DBPartidosLista;
import com.ayjsolutions.marcadoresfutbol.database.SQLPartidosLista;

// TODO: Auto-generated Javadoc
/**
 * Several auxiliary methods
 */
public class Utiles {

	/** The Constant URL_FLASHSCORE. */
	public static final String URL_FLASHSCORE = "http://www.flashscore.mobi/?s=1";

	/** The Constant URL_FLASHSCORE_LIVE. */
	public static final String URL_FLASHSCORE_LIVE = "http://www.flashscore.mobi/?s=2";

	/** The Constant URL_FLASHSCORE_FINISHED. */
	public static final String URL_FLASHSCORE_FINISHED = "http://www.flashscore.mobi/?s=3";

	/**
	 * Gets the partidos from the web page and parses all the matches into a
	 * list of PartidoLista
	 * 
	 * @param context
	 *            the context
	 * @param url_completa
	 *            the url_completa
	 * @return the partidos from soccer way
	 */
	public static List<PartidoLista> getPartidosFromSoccerWay(Context context,
			String url_completa) {

		// This method gets the Results from flash score

		List<PartidoLista> partidos = new ArrayList<PartidoLista>();

		HtmlCleaner html = new HtmlCleaner();
		CleanerProperties props = html.getProperties();
		props.setAllowHtmlInsideAttributes(true);
		props.setAllowMultiWordAttributes(true);
		props.setRecognizeUnicodeChars(true);
		props.setOmitComments(true);

		ArrayList<String> casa = new ArrayList<String>();
		ArrayList<String> golesCasa = new ArrayList<String>();
		ArrayList<String> fuera = new ArrayList<String>();
		ArrayList<String> golesFuera = new ArrayList<String>();
		ArrayList<String> tiempos = new ArrayList<String>();
		ArrayList<String> ligas = new ArrayList<String>();
		ArrayList<String> URLs = new ArrayList<String>();

		try {
			URL url = new URL(url_completa);
			TagNode tagNode = new HtmlCleaner(props).clean(url);
			Object[] nodes = tagNode.evaluateXPath("//div[@id='score-data']");

			TagNode node = (TagNode) nodes[0];
			List listaNodes = node.getChildren();

			int partido = 0;
			String ligaActual = "";
			for (int i = 0; i < listaNodes.size(); i++) {

				if (listaNodes.get(i).getClass().getName()
						.equals("org.htmlcleaner.TagNode")) {
					TagNode nodeActual = (TagNode) listaNodes.get(i);
					if (nodeActual.getName().equals("h4")) {
						ligaActual = nodeActual.getText().toString();
					} else if (nodeActual.getName().equals("span")) {

						if (nodeActual.getText().toString().contains("Postp")) {
							tiempos.add(" Post");
						} else if ((nodeActual.getText().toString()
								.contains("'") || nodeActual.getText()
								.toString().contains("T"))) {
							tiempos.add("  " + nodeActual.getText().toString());
						} else {
							tiempos.add(nodeActual.getText().toString());
						}
					} else if (nodeActual.getName().equals("a")
							&& (nodeActual.getAttributeByName("class").equals(
									"sched")
									|| nodeActual.getAttributeByName("class")
											.equals("fin") || nodeActual
									.getAttributeByName("class").equals("live"))) {

						String[] temporal = nodeActual.getText().toString()
								.split(":");
						golesCasa.add(temporal[0]);
						golesFuera.add(temporal[1]);
						ligas.add(ligaActual);
						URLs.add(nodeActual.getAttributeByName("href"));
					}
				} else {
					String[] temporal = listaNodes.get(i).toString()
							.split(" - ");
					if (temporal.length < 2)
						continue;
					if (temporal[0].equals("")) {
						temporal[0] = listaNodes.get(i-2).toString();
					}
					casa.add(temporal[0]);					
					fuera.add(temporal[1]);
				}
			}

			for (int i = 0; i < casa.size(); i++) {

				if (i == 0 || !ligas.get(i).equals(ligas.get(i - 1))) {
					// we add the name of the league if there is a change
					PartidoLista partidoTemp = new PartidoLista();
					partidoTemp.setHomeGoals("liga");
					partidoTemp.setVisitorGoals("liga");
					partidoTemp.setTime("liga");
					partidoTemp.setHomeTeam("liga");
					partidoTemp.setURL("liga");
					partidoTemp.setVisitorTeam("liga");
					partidoTemp.setLiga(ligas.get(i));
					partidos.add(partidoTemp);
				}
				PartidoLista partidoTemp = new PartidoLista();
				partidoTemp.setHomeGoals(golesCasa.get(i));
				partidoTemp.setVisitorGoals(golesFuera.get(i));
				partidoTemp.setTime(tiempos.get(i));
				partidoTemp.setHomeTeam(casa.get(i));
				partidoTemp.setVisitorTeam(fuera.get(i));
				partidoTemp.setLiga(ligas.get(i));
				partidoTemp.setURL(URLs.get(i).replace("?s=2", "")
						.replace("?s=1", "").replace("?s=3", ""));
				partidoTemp.setFollow("0");
				partidos.add(partidoTemp);
			}

		} catch (IOException e) {
			Toast toast1 = Toast.makeText(context,
					"Unable to find URL with match data.",
					Context.BIND_IMPORTANT);
			toast1.show();
		} catch (XPatherException e) {
			Toast toast1 = Toast.makeText(context, "XPath parsing exception: "
					+ e.getMessage(), Context.BIND_IMPORTANT);
			toast1.show();
		} catch (Exception e) {
			Toast toast1 = Toast.makeText(context, "XPath parsing exception: "
					+ e.getMessage(), Context.BIND_IMPORTANT);
			toast1.show();
		}

		return partidos;

	}

	/**
	 * Gets the log tags.
	 * 
	 * @param id
	 *            the id
	 * @return the log tags
	 */
	public static String getLogTags(int id) {

		String error = null;

		switch (id) {
		case 1:
			error = "Match_Exists";
			break;
		case 2:
			error = "DB_inserted";
			break;
		case 3:
			error = "DB_deleted";
			break;
		case 4:
			error = "Liga_found";
			break;
		case 5:
			error = "Db_not_found";
			break;
		case 6:
			error = "Refresh_match";
			break;
		}

		return error;

	}

	/**
	 * Gets the log comments.
	 * 
	 * @param id
	 *            the id
	 * @return the log comments
	 */
	public static String getLogComments(String id) {

		String error = null;

		if (id.equals("Match_Exists")) {
			error = "The match is already in the database. No insertion has been made.";
		} else if (id.equals("DB_inserted")) {
			error = "Match inserted in the database with id: ";
		} else if (id.equals("DB_deleted")) {
			error = "Matches from the league: ";
		} else if (id.equals("Db_not_found")) {
			error = "Db not found when trying to delete it. ";
		} else if (id.equals("Liga_found")) {
			error = "We found the league, returning the matches. ";
		} else if (id.equals("Refresh_match")) {
			error = "Refrshing the match. ";
		}

		return error;

	}

	/**
	 * Saves the database to another location in the SD card for debugging
	 * purposes.
	 */
	public static void savedatabase() {

		try {
			File sd = Environment.getExternalStorageDirectory();
			File data = Environment.getDataDirectory();

			if (sd.canWrite()) {
				String currentDBPath = "//data//com.example.marcadoresfutbol//databases//"
						+ SQLPartidosLista.DATABASE_NAME_PARTIDOS_LISTA;
				String backupDBPath = "backupname.db";
				File currentDB = new File(data, currentDBPath);
				File backupDB = new File(sd, backupDBPath);

				if (currentDB.exists()) {
					FileChannel src = new FileInputStream(currentDB)
							.getChannel();
					FileChannel dst = new FileOutputStream(backupDB)
							.getChannel();
					dst.transferFrom(src, 0, src.size());
					src.close();
					dst.close();
				}
			}
		} catch (Exception e) {

		}

	}

	public static void refreshPartidos(MainActivity context, int position) {

		List<PartidoLista> partidos = null;
		List<PartidoLista> partidosMostrar = new ArrayList<PartidoLista>();
		DBPartidosLista basedatos = new DBPartidosLista(context);
		basedatos.open();
		
		Log.i("Refreshing", "Enter refresPartidos();");

		SharedPreferences preferences = PreferenceManager
				.getDefaultSharedPreferences(context);
		if (preferences.getString("status", "DIRECTO").equals(
			preferences.getString("DIRECTO", "DIRECTO"))) {
			
			Log.i("Refreshing", "Retrieving live matches");

			partidos = Utiles.getPartidosFromSoccerWay(context,
					Utiles.URL_FLASHSCORE);
			ArrayList<String> partidosUpdateString = basedatos.getPartidosToUpdateString();
			

			List<String> partidosDirectoDB = basedatos.getPartidosLiveInDB();
			
			for (PartidoLista partido : partidos) {
				if (partidosDirectoDB.contains(partido.getURL()) && partido.getTime().contains(":")){
					// This match is not live anymore -> It has ended!!!
					partido.setTime(" FT");
					basedatos.refreshPartido(partido);
				}
				
			}			
			

			ArrayList<String> ligasDirecto = basedatos.getLigasDirecto();


			for (PartidoLista partido : partidos) {
				
				if (partidosUpdateString.contains(partido.getURL())){
					partido.setFollow("1");
				}
				
				try {
					basedatos.refreshPartido(partido);
					Log.i("Refreshing", "Refreshing match number " + partido.getId());
				} catch (Exception e) {
					Toast.makeText(context, "unable to refresh: " + e.getMessage(), 15).show();
				}

				// We show it if necessary
				if ((partido.getHomeTeam().equals("liga") && ligasDirecto.contains(partido.getLiga()))
						|| (context.ligasMostrar.contains(partido.getLiga()) && partido
								.getTime().contains("  "))) {
					partidosMostrar.add(partido);

				}
				
			}
		} else if (preferences.getString("status", "PROGRAMADOS").equals(
				preferences.getString("PROGRAMADOS", "PROGRAMADOS"))) {
			
			ArrayList<String> partidosToUpdate = basedatos.getPartidosToUpdateString();
			partidos = Utiles.getPartidosFromSoccerWay(context,
					Utiles.URL_FLASHSCORE);
			
			Log.i("Refreshing", "Retrieving all matches");
			for (PartidoLista partido : partidos) {
				try {
					basedatos.refreshPartido(partido);
					if (partidosToUpdate.contains(partido.getURL())){
						int state = basedatos.changeStatePartido(partido);
						partido.setFollow(Integer.toString(state));
					}
					if (partido.getHomeTeam().equals("liga")
							|| (context.ligasMostrar
									.contains(partido.getLiga()))) {
						partidosMostrar.add(partido);
					}
					
				} catch (Exception e) {
					Toast.makeText(context, "Unable to refresh: " + e.getMessage(), 15).show();
				}
			}

		} else if (preferences.getString("status", "ALERTAS").equals(
				preferences.getString("ALERTAS", "ALERTAS"))) {
			
			List<PartidoLista> partidosToUpdate = basedatos
					.getPartidosToUpdate();

			if (!partidosToUpdate.isEmpty()) {
				PartidoLista liga = new PartidoLista();
				liga.setTime("liga");
				liga.setHomeGoals("liga");
				liga.setVisitorGoals("liga");
				liga.setVisitorTeam("liga");
				liga.setHomeTeam("liga");
				liga.setTime("liga");
				liga.setURL("liga");
				liga.setLiga(partidosToUpdate.get(0).getLiga());
				partidosMostrar.add(liga);

				for (int i = 0; i < partidosToUpdate.size(); i++) {
					if (i > 0
							&& !partidosToUpdate
									.get(i)
									.getLiga()
									.equals(partidosToUpdate.get(i - 1)
											.getLiga())) {
						liga.setLiga(partidosToUpdate.get(i).getLiga());
						partidosMostrar.add(liga);
					}
					partidosMostrar.add(partidosToUpdate.get(i));
				}
			}
		}

		savedatabase();

		ListaPartidosAdapter lista = new ListaPartidosAdapter(context,
				partidosMostrar);
		context.setListAdapter(lista);
		lista.notifyDataSetChanged();
		try {
			basedatos.close();
		} catch (Exception e) {
			Log.w("REFRESHING", "Could not close database: ");
		}

	}

	public static List<PartidoLista> startDatabaseSession(Context context,
			int position) {

		List<PartidoLista> partidos = null;
		String status = PreferenceManager.getDefaultSharedPreferences(context)
				.getString("status", "DIRECTO");

		TimeZone zona = TimeZone.getDefault();
		zona.setRawOffset(2*3600*1000);
		Calendar today = Calendar.getInstance(zona);
		today.add(Calendar.HOUR, -1);
		int m = today.get(Calendar.MONTH) + 1;
		int d = today.get(Calendar.DATE);
		String mm = Integer.toString(m);
		String dd = Integer.toString(d);
		String todayString = "" + today.get(Calendar.YEAR)
				+ (m < 10 ? "0" + mm : mm) + (d < 10 ? "0" + dd : dd);

		DBPartidosLista basedatos = new DBPartidosLista(context);
		SQLPartidosLista sql = new SQLPartidosLista(context);

		basedatos.open();
		String dateString = basedatos.getDBDate();

		if (!dateString.equals(todayString) || position == 1) {

			partidos = Utiles.getPartidosFromSoccerWay(context,
					Utiles.URL_FLASHSCORE);
			try {
				context.deleteDatabase(sql.DATABASE_NAME_PARTIDOS_LISTA);
				basedatos = new DBPartidosLista(context);
				basedatos.open();
			} catch (Exception e) {
				Log.w(Utiles.getLogTags(5),
						Utiles.getLogComments(Utiles.getLogTags(5)));
			}
			PartidoLista date = new PartidoLista();
			date.setTime(todayString);

			basedatos.crearPartidoLista(date);

			for (PartidoLista partido : partidos) {
				try {
					basedatos.crearPartidoLista(partido);
				} catch (Exception e) {
					Toast.makeText(context, "unable to create match: " + e.getMessage(), 15).show();
				}
			}
		} else if (position == 0) {
			
			MainActivity activity = (MainActivity) context;
			refreshPartidos(activity, 1);

			partidos = basedatos.getAllPartidosAndLigas();
		}

		basedatos.close();

		return partidos;

	}
}
